package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.api.ArticleFeignClient;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.tess4j.Tess4jClient;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author DiXiaoNie
 * @since 2022/12/22 18:36
 */
@Service
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {

    @Autowired
    private WmNewsService wmNewsService;

    @Autowired
    private GreenTextScan greenTextScan;

    @Autowired
    private GreenImageScan greenImageScan;

    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private ArticleFeignClient articleFeignClient;

    @Autowired
    private WmUserService wmUserService;

    @Autowired
    private WmChannelService wmChannelService;

    @Autowired
    private WmSensitiveService wmSensitiveService;

    @Autowired
    private Tess4jClient tess4jClient;


    /**
     * 自动扫描wm新闻
     *
     * @param wmNewsId wm消息id
     * @author DiXiaoNie
     * @date 2022/12/22
     * @Async 表示当前方法是属于异步调用的
     */
    @Override
    @Async
    public void autoScanWmNews(Integer wmNewsId) {
        //1.根据文章id去查询文章是否存在
        WmNews wmNews = this.wmNewsService.getById(wmNewsId);
        if (wmNews == null) {
            return;
        }
        if (wmNews.getStatus().equals(WmNews.Status.SUBMIT.getCode())) {
            //1.1获取所有的文本和图片
            Map<String, Object> resultMap = extractionImageAndText(wmNews);
            //1.2 应该先子管理敏感词审核 只审核文本
            Boolean sensitiveFlag = handleTextSensitive((String) resultMap.get("content"), wmNews);
            if (!sensitiveFlag) {
                return;
            }

            //2.文章文本审核
            Boolean textFlag = handleTextScan((String) resultMap.get("content"), wmNews);
            if (!textFlag) {
                return;
            }
            //3.文章图片审核
            Boolean imageFlag = handleImageScan((List<String>) resultMap.get("imageUrlList"), wmNews);
            if (!imageFlag) {
                return;
            }
            //4.审核通过 保存
            ResponseResult result = saveAppArticle(wmNews);
            if (result.getCode() == 200) {
                //5.修改wm_news表的状态，设置article_id
                wmNews.setArticleId((Long) result.getData());
                updateWmNews(wmNews, (short) 9, "审核通过，文章已发布");
            }
        }
    }

    /**
     * 处理文本敏感
     *
     * @param content 内容
     * @param wmNews  wm新闻
     * @return {@link Boolean }
     * @author DiXiaoNie
     * @date 2022/12/24
     */
    private Boolean handleTextSensitive(String content, WmNews wmNews) {
        Boolean flag = Boolean.TRUE;
        //1.从数据库表中获取敏感词字段 只包含敏感词字段
        List<String> sensitivesList = this.wmSensitiveService.list(null)
                .stream()
                .map(WmSensitive::getSensitives)
                .collect(Collectors.toList());
        //2.对敏感词集合进行初始化操作DFA算法
        SensitiveWordUtil.initMap(sensitivesList);
        //3.拿文本内容进行匹配DFA算法 查看是否命中敏感词以及次数
        Map<String, Integer> integerMap = SensitiveWordUtil.matchWords(content);
        //4.如果命中审核不通过  反之通过
        if (integerMap != null && integerMap.size() > 0) {
            flag = Boolean.FALSE;
            updateWmNews(wmNews, (short) 2, "文本中包含敏感词汇");
        }
        return flag;
    }

    /**
     * 保存
     *
     * @param wmNews wm新闻
     * @author DiXiaoNie
     * @date 2022/12/22
     */
    private ResponseResult saveAppArticle(WmNews wmNews) {
        //1.调用feign接口
        ArticleDto dto = new ArticleDto();
        BeanUtils.copyProperties(wmNews, dto);
        //文章的布局
        dto.setLayout(wmNews.getType());
        //作者
        dto.setAuthorId(wmNews.getUserId().longValue());
        WmUser wmUser = this.wmUserService.getById(wmNews.getUserId());
        if (wmUser != null) {
            dto.setAuthorName(wmUser.getName());
        }
        //频道
        dto.setChannelId(wmNews.getChannelId());
        WmChannel wmChannel = this.wmChannelService.getById(wmNews.getChannelId());
        if (wmChannel != null) {
            dto.setChannelName(wmChannel.getName());
        }
        dto.setCreatedTime(new Date());
        ResponseResult result = this.articleFeignClient.save(dto);
        return result;

    }

    private Boolean handleImageScan(List<String> imageUrlList, WmNews wmNews) {
        Boolean flag = Boolean.TRUE;

        try {
            ArrayList<byte[]> imageByteList = new ArrayList<>();
            imageUrlList = imageUrlList.stream().distinct().collect(Collectors.toList());
            for (String imageUrl : imageUrlList) {
                byte[] bytes = this.fileStorageService.downLoadFile(imageUrl);

                //识别ocr
                ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
                BufferedImage bufferedImage = ImageIO.read(inputStream);
                //图片中的文字
                String resultText = this.tess4jClient.doOCR(bufferedImage);
                //图片文本审核
                Boolean textSensitiveFlag = handleTextSensitive(resultText, wmNews);
                if (!textSensitiveFlag) {
                    return Boolean.FALSE;
                }
                imageByteList.add(bytes);
            }
            //1.直接调用阿里云图片审核
            Map map = this.greenImageScan.imageScan(imageByteList);
            if (map != null && map.size() > 0) {
                if (map.get("suggestion").equals("block")) {
                    //修改status=2
                    updateWmNews(wmNews, (short) 2, "图片中包含敏感词汇");
                    flag = Boolean.FALSE;
                } else if (map.get("suggestion").equals("review")) {
                    //属于人工审核
                    //修改status=3
                    updateWmNews(wmNews, (short) 3, "图片中包含了不确定的信息");
                    flag = Boolean.FALSE;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            flag = Boolean.FALSE;
        }


        return flag;
    }

    /**
     * 处理文本扫描
     *
     * @param content 内容
     * @return {@link Boolean }
     * @author DiXiaoNie
     * @date 2022/12/22
     */
    private Boolean handleTextScan(String content, WmNews wmNews) {
        Boolean flag = Boolean.TRUE;
        try {
            Map map = this.greenTextScan.greeTextScan(content);
            if (map != null && map.size() > 0) {
                if (map.get("suggestion").equals("block")) {
                    //修改status=2
                    updateWmNews(wmNews, (short) 2, "文本中包含敏感词汇");
                    flag = Boolean.FALSE;
                } else if (map.get("suggestion").equals("review")) {
                    //属于人工审核
                    //修改status=3
                    updateWmNews(wmNews, (short) 3, "文本中包含了不确定的词汇");
                    flag = Boolean.FALSE;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            flag = Boolean.FALSE;
        }

        return flag;
    }

    /**
     * 更新wm新闻
     *
     * @param wmNews  wm新闻
     * @param status  状态
     * @param message 消息
     * @author DiXiaoNie
     * @date 2022/12/22
     */
    private void updateWmNews(WmNews wmNews, short status, String message) {

        wmNews.setStatus(status);
        wmNews.setReason(message);
        this.wmNewsService.updateById(wmNews);
    }

    /**
     * 提取图像和文本
     *
     * @param wmNews wm新闻
     * @author DiXiaoNie
     * @date 2022/12/22
     */
    private Map<String, Object> extractionImageAndText(WmNews wmNews) {
        //声明一个stringBuilder 封装抽取出来的文本
        StringBuilder builder = new StringBuilder();
        //声明一个list集合 封装抽取出来的图片
        List<String> imageUrlList = new ArrayList<>();

        //抽取文本
        String wmNewsTitle = wmNews.getTitle();
        builder.append(wmNewsTitle);
        String wmNewsContent = wmNews.getContent();
        List<Map> wmNewsContentList = JSON.parseArray(wmNewsContent, Map.class);
        for (Map map : wmNewsContentList) {
            //表示文本
            if (map.get("type").equals("text")) {
                String text = (String) map.get("value");
                builder.append(text);
            }
            //表示图片
            if (map.get("type").equals("image")) {
                String imageUrl = (String) map.get("value");
                imageUrlList.add(imageUrl);
            }
        }
        //封面图片
        String[] images = wmNews.getImages().split(",");
        imageUrlList.addAll(Arrays.asList(images));

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("content", builder.toString());
        resultMap.put("imageUrlList", imageUrlList);

        return resultMap;
    }
}
